#include "netinet/in.h"
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/netlink.h>
#include <asm/types.h>
#include <stdarg.h>
#include "sdk.h"
#include "sdk_port.h"

char *netcardName="enp0s8";

int sdk_port_random_get(void)
{
    static int random = 0x1234;

    random+=1;
    unsigned long nowustime=0;
    struct timeval nowtime;
    gettimeofday(&nowtime,NULL);
    nowustime = nowtime.tv_sec;
    nowustime = nowustime * 1000000 + nowtime.tv_usec;

    return nowustime & 0xFFFFFFFF;
}



//========================socket=============================

int sdk_port_udp_socket_create(int * fd,unsigned short port)
{
    int ret = -1;
    struct sockaddr_in addr;
    if(fd==NULL){
        printf("%s null pointer.",__FUNCTION__);
        return ret;
    }

    //socket create
    *fd =  socket(AF_INET,SOCK_DGRAM,0);
    if(*fd == -1){
        printf("%s:socket create error.",__FUNCTION__);
        return ret;
    }
    //set addr
    memset(&addr,0,sizeof(addr));
    addr.sin_family  =  AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(port);

    //bind
    if(bind(*fd,(struct sockaddr*)&addr,sizeof(addr)) != 0){
        printf("%s: bind error.",__FUNCTION__);
        goto _out;
    }

    return 0;

_out:
    if(*fd){
        close(*fd);
        *fd = -1;
    }


    return ret;


}


int sdk_port_udp_socket_close(int *sockfd)
{
    close(*sockfd);
    *sockfd = -1;
    return 0;
}

int sdk_port_socket_sendto(int fd, const void *buf, long unsigned int len, int flags, const struct sockaddr *target_addr, unsigned int target_len)
{
	int ret = sendto(fd, buf, len, flags, target_addr, target_len);
	if(ret > 0)
		return len;

	return -1;
}

int sdk_port_socket_recvform(int fd, void *buf, long unsigned int len, int flags, struct sockaddr *source_addr, unsigned int *source_len)
{
	return recvfrom(fd,buf, len, flags, source_addr, source_len);
}



unsigned int sdk_port_htonl(unsigned int hostlong)
{
	return htonl(hostlong);
}

unsigned short sdk_port_htons(unsigned short n)
{
	return htons(n);
}

unsigned short sdk_port_ntohs(unsigned short n)
{
	return ntohs(n);
}

unsigned int sdk_port_inet_addr(const char *cp)
{
	return inet_addr(cp);
}

int sdk_port_get_mac_addr(unsigned char *mac_addr)
{
    struct ifreq ifr;
    struct ifconf ifc;
    char buf[1024]={0};
    //int success = 0;
    int ret = -1;

    int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
    if (sock == -1) {
        printf("%s: socket error.",__FUNCTION__);
        return -1;
    }
 
    ifc.ifc_len = sizeof(buf);
    ifc.ifc_buf = buf;
    if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) {
        printf("%s: ioctl error.",__FUNCTION__);
        goto END;;
    }
 
    struct ifreq* it = ifc.ifc_req;
    const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));
    char szMac[64];
    int count = 0;
    for (; it != end; ++it) {
        strcpy(ifr.ifr_name, it->ifr_name);
        if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0) {
            if (! (ifr.ifr_flags & IFF_LOOPBACK)) { // don't count loopback
                if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) {
                    count ++ ;
                    unsigned char * ptr ;
                    ptr = (unsigned char  *)&ifr.ifr_ifru.ifru_hwaddr.sa_data[0];
                    snprintf(szMac,64,"%02X:%02X:%02X:%02X:%02X:%02X",*ptr,*(ptr+1),*(ptr+2),*(ptr+3),*(ptr+4),*(ptr+5));
                    
                    if (strcmp(ifr.ifr_name, netcardName)==0)
                    {
                        memcpy(mac_addr, ptr, 6);
                        ret = 0;
                        goto END;
                    }
                }
            }
        }else{
            printf("get mac info error");
            goto END;
        }
    }

END:
	close(sock);
    return ret;

}

int sdk_port_get_ip(char *ipstr)
{
    int inet_sock = -1;
    struct ifreq ifr;
    inet_sock = socket(AF_INET,SOCK_DGRAM,0);
    strcpy(ifr.ifr_name,netcardName);

    if(ioctl(inet_sock,SIOCGIFADDR,&ifr)<0){
        perror("ioctl");
        return SDK_SOCKIOCTL_ERR;
    }
    char *ip=inet_ntoa(((struct sockaddr_in*)&(ifr.ifr_addr))->sin_addr);
    strcpy(ipstr,ip);
    return inet_addr(ipstr);
}





/*
int sdk_port_tcp_socket_create(int * fd,unsigned short port)
{

    int ret = -1;
    struct sockaddr_in addr;
    if(fd==NULL){
        //ya_printf(C_LOG_ERROR,"%s: null pointer.\r\n",__FUNCTION__);
        sdk_printf("%s: null pointer.",__FUNCTION__);
        return ret;
    }

    //socket create
    *fd =  socket(AF_INET,SOCK_STREAM,0);
    if(*fd == -1){
        //ya_printf(C_LOG_ERROR,"%s:socket create error.\r\n",__FUNCTION__);
        sdk_printf("%s:socket create error.",__FUNCTION__);
        return ret;
    }
    //set addr
    memset(&addr,0,sizeof(addr));
    addr.sin_family  =  AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(port);

    //bind
    if(bind(*fd,(struct sockaddr*)&addr,sizeof(addr)) != 0){
        //ya_printf(C_LOG_ERROR,"%s: bind error.\r\n",__FUNCTION__);
        sdk_printf("%s: bind error.",__FUNCTION__);
        goto _out;
    }

    //listen 
    if(listen(*fd,5)!=0){
        //ya_printf(C_LOG_ERROR,"%s: listen error.\r\n",__FUNCTION__);
        sdk_printf("%s: listen error.",__FUNCTION__);
        goto _out;
    }

    return 0;

_out:
    if(*fd){
        close(*fd);
        *fd = -1;
    }


    return ret;
}
*/



int sdk_port_thread_create(sdk_port_thread_t *thandle, const char *name,void*(*main_func)(void *arg),
											void *arg,int stack_depth,int priority)
{

	if (pthread_create(thandle, NULL, main_func, arg))
		return -1;

	return 0;
}

int sdk_port_thread_delete(sdk_port_thread_t *thandle)
{
	pthread_cancel(*thandle);
	return 0;
}

void sdk_port_thread_sleep(int mses)
{
	usleep(mses * 1000);
	return;
}

void sdk_port_thread_suspend(sdk_port_thread_t *thandle)
{

	return;
}

void sdk_port_thread_resume(sdk_port_thread_t *thandle)
{
	return;
}
		

int sdk_port_printf(const char *fmt,...)
{
    va_list args;
    va_start(args,fmt);
    vprintf(fmt,args);
    va_end(args);
    return 0;
}

